package com.zx.callback.common.aop;

import com.zx.callback.common.enums.MessageEnumTable;
import com.zx.callback.common.ex.JsonResponseException;
import com.zx.callback.controller.BaseController;
import com.zx.callback.common.ex.ViewValidationException;
import com.zx.callback.vo.JsonResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.lang.reflect.Method;

/**
 * RequestMapping 代理层
 * Created by yanst on 2015/10/23.
 */
@Component
@Aspect
public class RequestMappingAop {
    private static final Logger LOG = LoggerFactory.getLogger(RequestMappingAop.class);

    private static final String ERROR_VIEW = "error";//错误调整页面

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping))")
    public void cutController(){
        LOG.debug("其诶单");
    }

    @Around("cutController()")
    public Object proceedController(ProceedingJoinPoint point){
        long start = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        Class<?> classes = method.getReturnType();

        Object obj = null;
        if (point.getTarget() instanceof BaseController) {
//            BaseApi baseApi = (BaseApi) point.getTarget();
            //1.异常处理
            try {
                obj = point.proceed();
            }catch (JsonResponseException e){
                LOG.error("请求接口：{}，错误信息：{}", requestMapping.value(), e.getMessage());
                obj = jsonError(e.getMessageEnumTable(), classes, method);
            }catch (ViewValidationException e) {
                LOG.error("非法请求接口：{}，非法错误信息：{}",requestMapping.value(), e.getMessage());
                obj = viewError(obj, classes, method);
            }
            catch (Throwable e) {
                LOG.error("请求接口：{}，错误信息：{}", requestMapping.value(), e.getMessage(),e);
            obj = error(obj, null ,classes, method);
//                obj = e;
            }
        } else {
            try {
                obj = point.proceed();
            }catch (JsonResponseException e){
                LOG.error("用户id为：{},请求接口：{}，错误信息：{}",null , requestMapping.value(), e.getMessage());
                obj = jsonError(e.getMessageEnumTable(), classes, method);
            }catch (Throwable e) {
                LOG.error("用户id为：{},请求接口：{}，错误信息：{}",null , requestMapping.value(), e.getMessage(),e);
            obj = error(obj, null ,classes, method);
//                obj = e;
            }
        }

        return obj;
    }

    /**
     * 异常总出口
     * @param obj
     * @param classes
     * @param method
     * @return
     */
    private Object error(Object obj, MessageEnumTable messageEnumTable, Class<?> classes, Method method){
        boolean result = isResultResponseBody(method);
        if(result){//json 输出
            obj = resultExceptionJson(messageEnumTable);
        }else {//view渲染
            if(classes.equals(ModelAndView.class)){
                ModelAndView mv = new ModelAndView(ERROR_VIEW);
                obj = mv;
            }else{
                obj = ERROR_VIEW;
            }
        }
        return obj;
    }

    /**
     * 异常总出口
     * @param classes
     * @param method
     * @return
     */
    private Object jsonError(MessageEnumTable messageEnumTable, Class<?> classes, Method method){
       return error(null, messageEnumTable, classes,  method);
    }

    /**
     * 异常总出口
     * @param classes
     * @param method
     * @return
     */
    private Object viewError(Object obj, Class<?> classes, Method method){
        return error(obj, null, classes,  method);
    }

    /**
     * 判断是否是ResponseBody 返回
     * @param method
     * @return
     */
    private boolean isResultResponseBody(Method method){
        String aClass = method.getReturnType().getCanonicalName();
            if("com.cy.saas.web.vo.JsonResult".equals(aClass)){
                return true;//json 输出
            }
        return false;
    }

    /**
     * 把异常转换为JsonResult 对象
     * @param messageEnumTable
     * @return
     */
    private JsonResult resultExceptionJson(MessageEnumTable messageEnumTable){
        JsonResult jsonResult = null;
        if(messageEnumTable == null){
            jsonResult = new JsonResult(MessageEnumTable.SYS__999);
        }else {
            jsonResult = new JsonResult(messageEnumTable);
        }
        return jsonResult;
    }
}
